﻿using System;
using System.Net;
using System.Text;

namespace npunkliner.lib
{
    public class PacketInfo
    {
        string hostName;
        int offset;
        bool isOnline;

        public EndPoint EndPoint { get; set; }
        public byte[] PacketData { get; set; }

        /// <summary>
        /// Gets the name of the host.
        /// </summary>
        /// <value>The name of the host.</value>
        public string HostName
        {
            get { return hostName; }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is valid.
        /// </summary>
        /// <value><c>true</c> if this instance is valid; otherwise, <c>false</c>.</value>
        public bool IsValid
        {
            get
            {
                return offset != 16 && (PacketData[offset] == 1 || PacketData[offset] == 15);
            }
        }

        /// <summary>
        /// Gets a value indicating whether [online status].
        /// </summary>
        /// <value><c>true</c> if [online status]; otherwise, <c>false</c>.</value>
        public bool IsOnline
        {
            get { return isOnline; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PacketInfo"/> class.
        /// </summary>
        public PacketInfo(byte[] packetData)
        {
            PacketData = packetData;
            offset = RetrieveOffset();
            hostName = RetrieveHostName();
            isOnline = RetrieveOnlineStatus(offset);
        }

        /// <summary>
        /// Retrieves the name of the hex.
        /// </summary>
        /// <param name="packetData">The packet data.</param>
        /// <returns></returns>
        public static byte[] RetrieveHexName(byte[] packetData)
        {
            byte[] nameHex = new byte[33];
            Array.Copy(packetData, 14, nameHex, 0, 32);
            return nameHex;
        }

        /// <summary>
        /// Retrieves the name of the host.
        /// </summary>
        /// <returns></returns>
        private string RetrieveHostName()
        {
            return DecodeName(RetrieveHexName(PacketData));
        }

        /// <summary>
        /// Retrieves the offset.
        /// </summary>
        /// <returns></returns>
        private int RetrieveOffset()
        {
            return ToString().ToUpper().IndexOf(@"\MAILSLOT\BROWSE") + 17;
        }

        /// <summary>
        /// Retrieves the online status of the host
        /// </summary>
        /// <param name="offset">The offset.</param>
        /// <returns></returns>
        private bool RetrieveOnlineStatus(int offset)
        {
            return ((PacketData[offset + 24] & 2) >> 1) == 1;
        }

        /// <summary>
        /// Decodes the name.
        /// </summary>
        /// <param name="nameBinary">The name binary.</param>
        /// <returns></returns>
        private static string DecodeName(byte[] nameBinary)
        {
            StringBuilder nameStringBuilder = new StringBuilder();

            for (int i = 1; i < nameBinary.Length - 2; i += 2)
            {
                if (nameBinary[i] == 67 && nameBinary[i + 1] == 65)
                    break;

                byte nameByte = (byte)((nameBinary[i] - 65 << 4) + (nameBinary[i + 1] - 65 & 0xf));
                string nameSymbol = Encoding.ASCII.GetString(new byte[] { nameByte });

                nameStringBuilder.Append(nameSymbol);
            }
            return nameStringBuilder.ToString();
        }

        /// <summary>
        /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </returns>
        public override string ToString()
        {
            return Encoding.ASCII.GetString(PacketData);
        }
    }
}
